#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
AI服务模块 - 大模型接入和智能解读
集成DeepSeek V3模型，提供法律条文智能解读功能
"""

import requests
import json
import logging
from typing import Dict, List, Optional, Any
from functools import lru_cache
from flask import current_app
import time
import hashlib
from .civil_code_service import CivilCodeService

MIN_SCENARIO_LENGTH = 10 # 定义最小场景描述长度

logger = logging.getLogger(__name__)

class AIService:
    """AI服务类 - 处理大模型调用和智能解读"""
    
    def __init__(self):
        self.api_url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
        # 初始化数据库服务，用于查询条文完整内容
        logger.info("=" * 100)
        logger.info("🚀🚀🚀 [AI服务初始化] AIService v1.3 正在启动...")
        logger.info("📦 [新功能] 已集成数据库查询功能，条文内容将从MongoDB直接获取")
        logger.info("=" * 100)
        self.civil_code_service = CivilCodeService()
        self.api_key = None
        self.model_name = "deepseek-v3-1-terminus"
        self.max_retries = 3
        self.timeout = 30
        self._init_config()
    
    def _init_config(self):
        """初始化AI服务配置"""
        try:
            # 从环境变量或配置文件获取API密钥
            import os
            self.api_key = os.getenv('AI_API_KEY', '546e703c-d17b-4adb-accc-30ef44707642')
            
            if not self.api_key:
                logger.warning("AI API密钥未配置，AI功能将不可用")
                
        except Exception as e:
            logger.error(f"AI服务初始化失败: {e}")
    
    def _make_request(self, messages: List[Dict], **kwargs) -> Optional[Dict]:
        """发送请求到AI模型"""
        if not self.api_key:
            logger.error("AI API密钥未配置")
            return None
        
        headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }
        
        payload = {
            "model": self.model_name,
            "messages": messages,
            **kwargs
        }
        
        for attempt in range(self.max_retries):
            try:
                logger.debug(f"AI请求 (尝试 {attempt + 1}/{self.max_retries}): {json.dumps(payload, ensure_ascii=False)}")
                
                response = requests.post(
                    self.api_url,
                    headers=headers,
                    json=payload,
                    timeout=self.timeout
                )
                
                if response.status_code == 200:
                    result = response.json()
                    logger.debug(f"AI响应成功: {result}")
                    return result
                else:
                    logger.error(f"AI请求失败 (状态码: {response.status_code}): {response.text}")
                    
            except requests.exceptions.Timeout:
                logger.warning(f"AI请求超时 (尝试 {attempt + 1}/{self.max_retries})")
            except requests.exceptions.RequestException as e:
                logger.error(f"AI请求异常 (尝试 {attempt + 1}/{self.max_retries}): {e}")
            except Exception as e:
                logger.error(f"AI请求未知错误 (尝试 {attempt + 1}/{self.max_retries}): {e}")
            
            if attempt < self.max_retries - 1:
                time.sleep(2 ** attempt)  # 指数退避
        
        return None
    
    def _extract_content(self, response: Dict) -> Optional[str]:
        """从AI响应中提取内容"""
        try:
            if 'choices' in response and len(response['choices']) > 0:
                choice = response['choices'][0]
                if 'message' in choice and 'content' in choice['message']:
                    return choice['message']['content'].strip()
        except Exception as e:
            logger.error(f"提取AI响应内容失败: {e}")
        
        return None
    
    def _call_ai_model(self, prompt: str, max_tokens: int = 2000) -> str:
        """统一的AI模型调用方法"""
        messages = [
            {"role": "system", "content": "你是一位专业的法律专家，专门解读中华人民共和国民法典。请确保提供详细、完整的分析。"},
            {"role": "user", "content": prompt}
        ]
        
        logger.debug(f"发送AI请求, max_tokens={max_tokens}")
        response = self._make_request(messages, temperature=0.7, max_tokens=max_tokens)
        if response:
            content = self._extract_content(response)
            if content:
                logger.debug(f"AI返回内容长度: {len(content)}字符")
                return content
            else:
                logger.error(f"无法从AI响应中提取内容: {response}")
        else:
            logger.error("AI请求返回None")
        
        raise Exception("AI模型调用失败")

    def explain_article(self, article_content: str) -> str:
        """
        解释法律条文
        
        Args:
            article_content: 法律条文内容
            
        Returns:
            str: AI生成的解释
        """
        prompt = f"请用通俗易懂的语言解释以下法律条文，并举一个生活中的例子：\n\n条文：\n{article_content}\n\n解释和例子："
        return self._call_ai_model(prompt)

    def answer_legal_question(self, question: str) -> str:
        """
        回答法律问题
        
        Args:
            question: 用户提出的问题
            
        Returns:
            str: AI生成的回答
        """
        prompt = f"请根据中国《民法典》的相关规定，回答以下法律问题：\n\n问题：\n{question}\n\n回答："
        return self._call_ai_model(prompt)

    def get_search_suggestions(self, query: str) -> list:
        """
        获取智能搜索建议（旧版本，保留兼容）
        
        Args:
            query: 用户输入的搜索词
            
        Returns:
            list: AI生成的搜索建议列表
        """
        prompt = f"根据以下搜索词，生成5个相关的、更具体的搜索建议，用于在中国《民法典》中搜索。请直接返回建议列表，用换行符分隔。\n\n搜索词：\n{query}\n\n建议："
        response = self._call_ai_model(prompt)
        return [line.strip() for line in response.split('\n') if line.strip()]
    
    def get_search_suggestions_enhanced(self, query: str) -> dict:
        """
        获取增强版搜索建议（v1.7）
        
        支持7种建议类型，包含丰富的元数据信息
        
        Args:
            query: 用户输入的搜索词
            
        Returns:
            dict: 包含建议列表和元数据的字典
        """
        logger.info("=" * 100)
        logger.info(f"🎯 [增强建议生成] 开始为关键词 '{query}' 生成v1.7增强建议")
        logger.info("=" * 100)
        
        try:
            # 1. 构建增强版Prompt
            prompt = self._build_suggestions_prompt_v17(query)
            
            # 2. 调用AI模型
            response = self._make_request(
                messages=[{"role": "user", "content": prompt}],
                max_tokens=3000,
                temperature=0.7
            )
            
            if not response:
                logger.error("❌ AI模型无响应")
                return self._get_fallback_suggestions(query)
            
            # 3. 提取内容
            content = self._extract_content(response)
            if not content:
                logger.error("❌ 无法提取AI响应内容")
                return self._get_fallback_suggestions(query)
            
            # 4. 解析JSON响应
            suggestions_data = self._parse_suggestions_json(content)
            
            # 5. 数据验证
            validated = self._validate_suggestions(suggestions_data)
            
            # 6. 返回结果
            result = {
                'suggestions': validated,
                'total': len(validated),
                'query': query,
                'version': '1.7'
            }
            
            logger.info(f"✅ [生成成功] 返回 {len(validated)} 条有效建议")
            return result
            
        except Exception as e:
            logger.error(f"❌ [生成失败] 增强建议生成异常: {e}", exc_info=True)
            return self._get_fallback_suggestions(query)
    
    def _build_suggestions_prompt_v17(self, query: str) -> str:
        """构建v1.7版本的增强Prompt（精简版-4种类型，口语化优化）"""
        prompt = f"""你是一位友好的法律顾问助手，用通俗易懂的语言为用户提供民法典搜索建议。

【用户输入】
{query}

【核心原则】
1. 使用口语化、问题式的表达，让用户感觉像在和朋友对话
2. 避免生硬的条目式标题，多用"如何"、"什么是"、"怎样"等疑问词
3. 让建议看起来像用户自己会问的问题

【建议类型要求】
必须包含以下4种类型，每种至少2-3条，总共10-12条：

1. **article** (条文查询) - 引导用户查询具体条文
   ❌ 错误示例："查询第240条物权法定原则"（太生硬）
   ✅ 正确示例："第240条讲的是什么？"、"我想了解物权法定原则"

2. **question** (法律问答) - 用户可能关心的问题
   ❌ 错误示例："物权和债权区别"（太简略）
   ✅ 正确示例："物权和债权有什么不同？"、"如何区分物权和债权？"

3. **scenario** (场景分析) - 生活化的场景描述
   ❌ 错误示例："相邻关系纠纷"（太专业）
   ✅ 正确示例："邻居家装修影响到我，怎么办？"、"遇到相邻纠纷该如何处理？"

4. **concept** (概念拓展) - 通俗化的概念解释
   ❌ 错误示例："用益物权定义"（太书面）
   ✅ 正确示例："什么是用益物权？"、"用益物权是什么意思？"

【输出格式】
严格按照以下JSON格式输出，不要包含markdown代码块标记：

{{
  "suggestions": [
    {{
      "type": "article",
      "text": "第240条讲的是什么？",
      "description": "查看物权法定原则的具体内容和法律意义",
      "action": "explain",
      "target": "第240条",
      "metadata": {{
        "related_articles_count": 5,
        "applicable_scenarios": ["物权确认", "权利保护", "财产纠纷"],
        "difficulty_level": "medium",
        "popularity": 85
      }}
    }},
    {{
      "type": "question",
      "text": "物权和债权有什么不同？",
      "description": "了解这两种权利的本质区别和实际影响",
      "action": "question",
      "target": "物权和债权有什么区别",
      "metadata": {{
        "related_articles_count": 8,
        "applicable_scenarios": ["权利理解", "合同履行", "纠纷处理"],
        "difficulty_level": "easy",
        "popularity": 92
      }}
    }},
    {{
      "type": "scenario",
      "text": "邻居家装修太吵怎么办？",
      "description": "分析相邻关系纠纷的处理方法和法律依据",
      "action": "scenario",
      "target": "相邻关系纠纷处理",
      "metadata": {{
        "related_articles_count": 6,
        "applicable_scenarios": ["邻里纠纷", "噪音扰民", "权益保护"],
        "difficulty_level": "easy",
        "popularity": 88
      }}
    }},
    {{
      "type": "concept",
      "text": "什么是用益物权？",
      "description": "用通俗语言解释用益物权的含义和常见例子",
      "action": "question",
      "target": "用益物权是什么",
      "metadata": {{
        "related_articles_count": 4,
        "applicable_scenarios": ["土地使用", "财产管理", "权利学习"],
        "difficulty_level": "medium",
        "popularity": 75
      }}
    }}
  ]
}}

【元数据说明】
- related_articles_count: 关联的民法典条文数量（1-20之间的整数）
- applicable_scenarios: 适用场景列表，最多3个，每个5-8字，简短精准
- difficulty_level: 必须是 easy（基础）、medium（中等）、hard（复杂）之一
- popularity: 热度指数（0-100之间的整数），可选

【action字段说明】
- article类型用 "explain"
- question类型用 "question"
- scenario类型用 "scenario"
- concept类型用 "question"

【重要提示】
1. 4种类型每种至少2条，总共10-12条
2. text必须口语化、问题式，像朋友间对话（12-25字）
3. description要通俗易懂，说明能得到什么帮助（18-35字）
4. action必须严格按上述规则选择
5. applicable_scenarios要生活化、具体，避免专业术语
6. 严格输出JSON格式，不要有markdown代码块标记（```json等）
7. 所有字段都是必填项，不要遗漏
8. 多使用疑问句："如何"、"怎么"、"什么是"、"能不能"、"可以吗"

【口语化风格示例】
✅ "房子买卖合同要注意什么？"
✅ "离婚时财产怎么分？"
✅ "借钱不还可以起诉吗？"
✅ "遗产继承有哪些顺序？"

请开始生成，记住要口语化、易懂、像朋友间的对话："""
        
        return prompt
    
    def _parse_suggestions_json(self, content: str) -> list:
        """解析AI返回的建议JSON"""
        logger.info("=" * 80)
        logger.info("📥 [JSON解析] 开始解析AI返回的建议JSON")
        logger.info(f"原始响应长度: {len(content)} 字符")
        
        # 清理markdown代码块标记
        cleaned = content.strip()
        if cleaned.startswith('```'):
            lines = cleaned.split('\n')
            cleaned = '\n'.join(lines[1:])
        if cleaned.endswith('```'):
            cleaned = cleaned.rsplit('\n', 1)[0]
        cleaned = cleaned.strip()
        
        logger.info(f"清理后内容前200字: {cleaned[:200]}...")
        
        try:
            data = json.loads(cleaned)
            suggestions = data.get('suggestions', [])
            logger.info(f"✅ JSON解析成功，获得 {len(suggestions)} 条建议")
            return suggestions
        except json.JSONDecodeError as e:
            logger.error(f"❌ JSON解析失败: {e}")
            logger.error(f"失败位置: 第{e.lineno}行, 第{e.colno}列")
            logger.error(f"失败内容片段: {cleaned[max(0, e.pos-50):e.pos+50]}")
            raise
    
    def _validate_suggestions(self, suggestions: list) -> list:
        """验证并规范化建议数据"""
        logger.info("=" * 80)
        logger.info(f"🔍 [数据验证] 开始验证 {len(suggestions)} 条建议")
        
        validated = []
        required_types = {'article', 'question', 'scenario', 'concept'}
        found_types = set()
        
        for idx, sug in enumerate(suggestions):
            try:
                # 验证必需字段
                if not all(k in sug for k in ['type', 'text', 'action', 'target']):
                    logger.warning(f"  ⚠️ 建议 {idx+1} 缺少必需字段，跳过")
                    continue
                
                # 补充缺失的description
                if 'description' not in sug or not sug['description']:
                    sug['description'] = sug['text']
                    logger.info(f"  📝 建议 {idx+1} 补充description")
                
                # 验证和补充metadata
                if 'metadata' not in sug or not isinstance(sug['metadata'], dict):
                    sug['metadata'] = self._generate_default_metadata(sug['type'])
                    logger.info(f"  📝 建议 {idx+1} 生成默认metadata")
                else:
                    meta = sug['metadata']
                    # 补充缺失的metadata字段
                    if 'related_articles_count' not in meta:
                        meta['related_articles_count'] = 3
                    if 'applicable_scenarios' not in meta or not meta['applicable_scenarios']:
                        meta['applicable_scenarios'] = []
                    if 'difficulty_level' not in meta:
                        meta['difficulty_level'] = 'medium'
                    # 限制场景数量
                    if len(meta['applicable_scenarios']) > 3:
                        meta['applicable_scenarios'] = meta['applicable_scenarios'][:3]
                
                validated.append(sug)
                found_types.add(sug['type'])
                logger.info(f"  ✅ 建议 {idx+1}: {sug['type']} - {sug['text']}")
                
            except Exception as e:
                logger.error(f"  ❌ 验证建议 {idx+1} 失败: {e}")
                continue
        
        # 检查类型覆盖
        missing_types = required_types - found_types
        if missing_types:
            logger.warning(f"⚠️ 缺少以下类型的建议: {missing_types}")
        
        logger.info(f"✅ [验证完成] 有效建议: {len(validated)}/{len(suggestions)} 条")
        logger.info(f"📊 类型分布: {dict((t, sum(1 for s in validated if s['type'] == t)) for t in found_types)}")
        logger.info("=" * 80)
        
        return validated
    
    def _generate_default_metadata(self, suggestion_type: str) -> dict:
        """生成默认元数据"""
        defaults = {
            'article': {'count': 1, 'scenarios': ['条文查询'], 'level': 'easy'},
            'question': {'count': 3, 'scenarios': ['法律咨询'], 'level': 'easy'},
            'scenario': {'count': 5, 'scenarios': ['案例分析'], 'level': 'medium'},
            'concept': {'count': 3, 'scenarios': ['概念学习'], 'level': 'easy'}
        }
        
        default = defaults.get(suggestion_type, defaults['question'])
        return {
            'related_articles_count': default['count'],
            'applicable_scenarios': default['scenarios'],
            'difficulty_level': default['level']
        }
    
    def _get_fallback_suggestions(self, query: str) -> dict:
        """降级建议（当AI失败时）"""
        logger.warning("⚠️ [降级策略] 使用基础降级建议")
        
        fallback = {
            'suggestions': [
                {
                    'type': 'article',
                    'text': f'搜索"{query}"相关条文',
                    'description': '在民法典中查找相关法律条文',
                    'action': 'explain',
                    'target': query,
                    'metadata': {
                        'related_articles_count': 3,
                        'applicable_scenarios': ['法律查询'],
                        'difficulty_level': 'easy'
                    }
                },
                {
                    'type': 'question',
                    'text': f'关于"{query}"的常见问题',
                    'description': '了解相关的法律问题和解答',
                    'action': 'question',
                    'target': f'{query}的法律规定',
                    'metadata': {
                        'related_articles_count': 5,
                        'applicable_scenarios': ['法律咨询'],
                        'difficulty_level': 'easy'
                    }
                },
                {
                    'type': 'scenario',
                    'text': f'"{query}"相关场景分析',
                    'description': '分析实际生活中的具体案例',
                    'action': 'scenario',
                    'target': f'{query}的实际案例',
                    'metadata': {
                        'related_articles_count': 4,
                        'applicable_scenarios': ['场景理解'],
                        'difficulty_level': 'medium'
                    }
                }
            ],
            'total': 3,
            'query': query,
            'version': '1.7-fallback'
        }
        
        logger.info(f"📦 [降级建议] 返回 {len(fallback['suggestions'])} 条基础建议")
        return fallback

    def _fetch_article_contents_from_db(self, article_numbers: list) -> dict:
        """
        从数据库批量获取条文的完整内容
        
        Args:
            article_numbers: 条文编号列表，如 ["第240条", "第323条"]
            
        Returns:
            dict: 条文编号到完整内容的映射
        """
        if not article_numbers:
            logger.warning("❌ 条文编号列表为空")
            return {}
        
        logger.info("=" * 80)
        logger.info(f"💾 [数据库查询] 准备从数据库查询 {len(article_numbers)} 个条文")
        logger.info(f"📋 条文列表: {article_numbers}")
        logger.info("=" * 80)
        
        content_map = {}
        
        try:
            for idx, number in enumerate(article_numbers):
                try:
                    # 从数据库查询条文
                    article = self.civil_code_service.get_article_by_number(number)
                    
                    if article and article.get('content'):
                        content_map[number] = {
                            'title': article.get('title', ''),
                            'content': article['content'],
                            'part': article.get('part', '民法典'),
                            'chapter': article.get('chapter', ''),
                            'chapter_path': article.get('chapter_path', '')
                        }
                        logger.info(f"  ✅ [{idx+1}/{len(article_numbers)}] {number} - 标题: '{article.get('title', '无')}' - 内容长度: {len(article['content'])}字")
                    else:
                        logger.warning(f"  ⚠️ [{idx+1}/{len(article_numbers)}] {number} - 数据库中未找到")
                        
                except Exception as e:
                    logger.error(f"  ❌ [{idx+1}/{len(article_numbers)}] {number} - 查询失败: {e}")
            
            logger.info("=" * 80)
            logger.info(f"🎉 [查询完成] 成功从数据库获取 {len(content_map)}/{len(article_numbers)} 个条文")
            logger.info("=" * 80)
            return content_map
            
        except Exception as e:
            logger.error(f"❌ [数据库查询失败] {e}", exc_info=True)
            return {}
    
    def analyze_case(self, target: str) -> str:
        """
        典型案例分析
        
        提供详细的案例分析，包括案例背景、争议焦点、法院观点、
        法律依据、实践启示等完整内容
        
        Args:
            target: 案例查询目标
            
        Returns:
            str: markdown格式的详细案例分析
        """
        logger.info(f"⚖️ [案例分析] 开始分析: {target}")
        
        prompt = f"""你是专业的法律案例分析专家。请针对用户的案例查询需求，提供详细的案例分析。

【用户查询】
{target}

【输出要求】
请按以下结构输出完整的案例分析：

## 1. 案例背景（100-150字）
简述案例的基本事实，包括：
- 当事人身份和关系
- 争议标的物或权利
- 纠纷的起因和发展过程

## 2. 争议焦点（列出3-5个核心法律争议点）
- **焦点1**：[具体争议点描述]
- **焦点2**：[具体争议点描述]
- **焦点3**：[具体争议点描述]

## 3. 法院观点（200-300字）
详细说明法院的裁判理由，包括：
- 法律适用分析
- 事实认定要点
- 判决的法律依据
- 裁判的逻辑推理过程

## 4. 法律依据（至少3条）
- **第XXX条** [条文标题]：[条文核心内容简述80-100字]
- **第XXX条** [条文标题]：[条文核心内容简述80-100字]
- **第XXX条** [条文标题]：[条文核心内容简述80-100字]

## 5. 实践启示（100-150字）
总结本案对普通民众的启示意义：
- 如何避免类似纠纷
- 需要注意的法律要点
- 权利保护的实践建议

## 6. 相似案例（可选，1-2个）
- **案例A**：[简述类似案例及其特点]
- **案例B**：[简述类似案例及其特点]

【格式要求】
- 使用清晰的markdown格式
- 重点内容使用**加粗**标记
- 条文编号必须**加粗**
- 结构清晰，层次分明
- 内容专业准确，通俗易懂
- 总字数控制在800-1200字

请开始分析："""

        return self._call_ai_model(prompt, max_tokens=2000)
    
    def analyze_pitfall(self, target: str) -> str:
        """
        常见误区分析
        
        澄清法律认知误区，对比错误认知和正确理解，
        提供法律依据和案例说明
        
        Args:
            target: 误区分析目标
            
        Returns:
            str: markdown格式的详细误区分析
        """
        logger.info(f"⚠️ [误区分析] 开始分析: {target}")
        
        prompt = f"""你是专业的法律科普专家。请针对用户关心的法律领域，澄清常见的法律认知误区。

【用户查询】
{target}

【输出要求】
请按以下结构输出完整的误区分析：

## 误区总览
列出该领域3-5个最常见的误区，每个用一句话概括：
1. [误区1标题]
2. [误区2标题]
3. [误区3标题]

## 详细解析

### 误区1：[误区标题]

❌ **错误认知**  
很多人认为：[详细描述错误的理解，80-100字]

✅ **正确理解**  
根据《民法典》的规定，实际应该是：[详细说明正确的法律理解，100-120字]

📖 **法律依据**  
**第XXX条** [条文标题]：[引用具体条文内容或核心要点，80-100字]

💡 **案例说明**  
举例：[用简单易懂的例子帮助理解，如"小王遇到...，正确的做法是...", 80-100字]

---

### 误区2：[误区标题]

❌ **错误认知**  
[同上格式]

✅ **正确理解**  
[同上格式]

📖 **法律依据**  
[同上格式]

💡 **案例说明**  
[同上格式]

---

### 误区3：[误区标题]

[同上格式]

---

## 特别提醒（100字左右）
强调需要特别注意的要点，帮助避免常见错误。

【格式要求】
- 使用emoji使内容生动（❌✅📖💡）
- 每个误区独立成段，用分隔线分开
- 法律条文**加粗**标注
- 案例简单易懂，贴近生活
- 对比鲜明，重点突出
- 总字数控制在800-1200字

请开始分析："""

        return self._call_ai_model(prompt, max_tokens=2000)
    
    def analyze_compare(self, target: str) -> str:
        """
        对比分析
        
        系统对比两个法律概念的异同，包括概念界定、核心差异、
        法律依据、实践应用和选择建议
        
        Args:
            target: 对比分析目标
            
        Returns:
            str: markdown格式的详细对比分析
        """
        logger.info(f"🔄 [对比分析] 开始分析: {target}")
        
        prompt = f"""你是专业的法律概念对比分析专家。请对用户关心的法律概念进行系统对比分析。

【用户查询】
{target}

【输出要求】
请按以下结构输出完整的对比分析：

## 1. 概念界定

### 概念A：[概念名称]
[50-80字定义，说明其法律含义、本质特征]

### 概念B：[概念名称]
[50-80字定义，说明其法律含义、本质特征]

## 2. 核心差异对比表

| 对比维度 | 概念A | 概念B |
|---------|-------|-------|
| **法律性质** | [30-50字说明] | [30-50字说明] |
| **适用范围** | [30-50字说明] | [30-50字说明] |
| **权利义务** | [30-50字说明] | [30-50字说明] |
| **法律效力** | [30-50字说明] | [30-50字说明] |
| **救济方式** | [30-50字说明] | [30-50字说明] |

## 3. 法律依据

### 概念A相关条文
- **第XXX条** [条文标题]：[核心内容简述，50-80字]
- **第XXX条** [条文标题]：[核心内容简述，50-80字]

### 概念B相关条文
- **第XXX条** [条文标题]：[核心内容简述，50-80字]
- **第XXX条** [条文标题]：[核心内容简述，50-80字]

## 4. 实践应用

### 概念A的典型场景（100字）
举例说明概念A在实际中的应用场景，如：[具体例子和应用情况]

### 概念B的典型场景（100字）
举例说明概念B在实际中的应用场景，如：[具体例子和应用情况]

## 5. 选择建议（100字）
在什么情况下适用哪个概念，如何做出正确选择：
- 当遇到[情况1]时，应选择概念A
- 当遇到[情况2]时，应选择概念B
- 实践中的判断要点

【格式要求】
- 使用markdown表格清晰展示对比
- 重点差异用**加粗**标记
- 条文编号清晰标注
- 建议具体实用，易于理解
- 总字数控制在800-1200字

请开始分析："""

        return self._call_ai_model(prompt, max_tokens=2000)
    
    def _normalize_articles(self, raw_articles) -> list:
        """
        规范化条文数据格式，确保返回对象数组
        
        Args:
            raw_articles: AI返回的原始条文数据（可能是字符串数组或对象数组）
            
        Returns:
            list: 规范化后的对象数组，每个对象包含 number, title, content
        """
        logger.info("=" * 80)
        logger.info("🔍 [智能补充机制] _normalize_articles() 被调用")
        logger.info(f"📥 原始数据类型: {type(raw_articles)}")
        logger.info(f"📥 原始数据内容: {raw_articles}")
        logger.info("=" * 80)
        
        if not raw_articles:
            logger.warning("❌ 条文数据为空")
            return []
        
        # 如果已经是对象数组且格式正确，直接返回
        if isinstance(raw_articles, list) and len(raw_articles) > 0:
            first_item = raw_articles[0]
            
            # 检查是否是完整的对象格式
            if isinstance(first_item, dict) and 'content' in first_item:
                logger.info(f"条文数据已是对象格式，包含 {len(raw_articles)} 条")
                # 验证所有对象都有必需字段
                normalized = []
                for idx, article in enumerate(raw_articles):
                    if isinstance(article, dict):
                        if article.get('content'):
                            normalized.append({
                                'number': article.get('number', f'条文{idx+1}'),
                                'title': article.get('title', ''),
                                'content': article['content']
                            })
                        else:
                            logger.warning(f"条文 {idx+1} 缺少 content 字段: {article}")
                return normalized
            
            # 如果是字符串数组，需要转换并补充内容
            if isinstance(first_item, str):
                logger.warning("=" * 80)
                logger.warning("⚠️ [字符串格式] 检测到AI返回的是字符串数组，将启动智能补充机制")
                logger.warning(f"📝 原始字符串数组: {raw_articles}")
                logger.warning("=" * 80)
                
                import re
                article_numbers = []
                
                # 第一步：提取所有条文编号
                for article_str in raw_articles:
                    match = re.match(r'(第\d+条)', article_str)
                    if match:
                        article_numbers.append(match.group(1))
                        logger.info(f"  ✓ 提取条文编号: {match.group(1)}")
                    else:
                        logger.warning(f"  ✗ 无法提取条文编号: {article_str}")
                
                # 第二步：从数据库批量获取完整内容
                if article_numbers:
                    content_map = self._fetch_article_contents_from_db(article_numbers)
                    
                    # 第三步：构建规范化的对象数组
                    logger.info("=" * 80)
                    logger.info("🔨 [构建对象] 正在构建标准化的对象数组...")
                    normalized = []
                    for idx, number in enumerate(article_numbers):
                        if number in content_map:
                            article_data = content_map[number]
                            article_obj = {
                                'number': number,
                                'title': article_data.get('title', ''),
                                'content': article_data['content']
                            }
                            normalized.append(article_obj)
                            logger.info(f"  ✅ [{idx+1}/{len(article_numbers)}] {number} - 标题: '{article_data.get('title', '无')}' - 内容: {len(article_obj['content'])}字")
                        else:
                            # 如果数据库中未找到，使用兜底内容
                            logger.warning(f"  ⚠️ [{idx+1}/{len(article_numbers)}] {number} 数据库中未找到，使用兜底提示")
                            normalized.append({
                                'number': number,
                                'title': '条文不存在',
                                'content': f'{number}在数据库中未找到，可能是条文编号错误或数据尚未录入。请核对条文编号或查阅《中华人民共和国民法典》官方文本。'
                            })
                    
                    logger.info("=" * 80)
                    logger.info(f"✨ [转换完成] 字符串数组 → 对象数组转换成功！（数据来源：数据库）")
                    logger.info(f"📦 [最终结果] 返回 {len(normalized)} 个完整的条文对象")
                    logger.info("=" * 80)
                    return normalized
                else:
                    logger.error("未能从字符串数组中提取任何条文编号")
                    return []
        
        logger.error(f"无法识别的条文数据格式: {type(raw_articles)}, {raw_articles}")
        return []

    def analyze_legal_scenario(self, scenario: str) -> dict:
        """
        分析法律场景
        
        Args:
            scenario: 用户描述的法律场景
            
        Returns:
            dict: AI生成的分析结果，或要求用户提供更多信息的反馈
        """
        
        # 1. 输入验证
        if len(scenario.strip()) < MIN_SCENARIO_LENGTH:
            logger.info(f"场景描述过短 (长度: {len(scenario.strip())}), 要求更多信息。")
            return {
                "feedback": {
                    "type": "MORE_INFO_NEEDED",
                    "message": "您提供的信息太少了，无法进行有效的法律分析。请尝试描述一个更具体的情景，例如时间、地点、人物和事件。",
                    "suggestions": [
                        "遇到了什么问题？",
                        "涉及哪些人或物？",
                        "事情发生的经过是怎样的？"
                    ]
                }
            }

        prompt = f"""⚠️ 关键要求：related_articles 必须是对象数组，每个对象必须包含 number、title、content 三个完整字段！

你是专业的法律分析专家。请分析以下法律场景，用通俗易懂的语言和具体案例帮助用户理解。

【用户场景】
{scenario}

【分析要求】
1. 用简单的语言解释法律概念
2. 提供具体的案例来说明
3. 让用户能够理解抽象的法律规定在实际生活中如何应用

【JSON输出格式 - 严格遵守】
{{
  "analysis": {{
    "key_points": [
      "场景一：[具体案例场景]。解析：[通俗易懂的解释]",
      "场景二：[具体案例场景]。解析：[通俗易懂的解释]",
      "场景三：[具体案例场景]。解析：[通俗易懂的解释]"
    ],
    "related_articles": [
      {{
        "number": "第XXX条",
        "title": "条文标题",
        "content": "《中华人民共和国民法典》该条文的完整原文（必须完整，不得省略）"
      }}
    ],
    "preliminary_advice": "结合案例的具体建议，告诉用户在这种情况下应该怎么做（不少于100字）"
  }}
}}

【案例示例 - 参考格式】
如果用户问："我租的房子还没到期，房东突然要把房子卖了，让我搬走"

key_points 应该这样写：
[
  "案例场景：小王租了房东李先生的房子，签了2年合同才住了1年。李先生突然说要卖房，让小王下月搬走。解析：这违反了'买卖不破租赁'原则，即使房子卖了，租赁合同仍然有效，小王有权继续住到合同期满。",
  "案例场景：房东决定卖房后，应该提前通知小王，给小王优先购买的机会。如果小王不买，房子卖给别人后，小王仍然可以按原合同继续租住。解析：这是法律保护承租人的重要规定，防止房东随意终止租约。",
  "案例场景：如果房东强制要求小王搬走，小王可以拒绝，并要求房东继续履行合同。如果房东造成损失，小王还可以要求赔偿。解析：租赁合同是受法律保护的，任何一方不能单方面违约。"
]

【❌ 错误的key_points - 禁止】
[
  "租赁合同受法律保护",  ← 太抽象，用户看不懂
  "买卖不破租赁原则",    ← 只是名词，没有解释
  "承租人有权继续居住"   ← 缺少具体场景
]

【✅ related_articles 正确格式】
[
  {{
    "number": "第725条",
    "title": "买卖不破租赁原则", 
    "content": "租赁物在承租人按照租赁合同占有期限内发生所有权变动的，不影响租赁合同的效力。"
  }},
  {{
    "number": "第726条",
    "title": "承租人的优先购买权",
    "content": "出租人出卖租赁房屋的，应当在出卖之前的合理期限内通知承租人，承租人享有以同等条件优先购买的权利；但是，房屋按份共有人行使优先购买权或者出租人将房屋出卖给近亲属的除外。出租人履行通知义务后，承租人在十五日内未明确表示购买的，视为承租人放弃优先购买权。"
  }}
]

【强制要求】
1. key_points 必须是"案例场景+解析"的格式，不要只写抽象的法律名词
2. related_articles 是对象数组，每个对象必须有 number、title、content 三个字段
3. content 必须是完整的民法典原文，不得省略或概括
4. preliminary_advice 要结合具体案例给建议，告诉用户具体怎么做
5. 至少返回2-3个相关条文
6. 不要添加markdown标记（如```json）

现在请按照上述格式分析用户场景:"""

        logger.info(f"🎯 开始场景分析: {scenario[:50]}...")
        logger.info("📋 提示词已强化，要求AI必须返回对象数组格式")
        
        try:
            response_str = self._call_ai_model(prompt, max_tokens=3000)  # 增加token限制以容纳完整条文
            logger.info(f"AI返回原始响应长度: {len(response_str)}字符")
            logger.debug(f"AI原始响应内容: {response_str[:500]}...")
            
        except Exception as e:
            logger.error(f"AI模型调用失败: {e}")
            return {
                "analysis": {
                    "key_points": ["AI服务暂时不可用"],
                    "related_articles": [],
                    "preliminary_advice": f"抱歉,AI服务调用失败: {str(e)}。请稍后重试或联系技术支持。"
                }
            }
        
        try:
            # 清理AI返回的Markdown代码块标记
            clean_response = response_str.strip()
            
            # 移除可能的markdown标记
            if clean_response.startswith("```json"):
                clean_response = clean_response[7:]
                logger.debug("移除了```json标记")
            elif clean_response.startswith("```"):
                clean_response = clean_response[3:]
                logger.debug("移除了```标记")
                
            if clean_response.endswith("```"):
                clean_response = clean_response[:-3]
                logger.debug("移除了末尾```标记")
                
            clean_response = clean_response.strip()
            logger.debug(f"清理后的响应: {clean_response[:300]}...")
            
            # 解析JSON
            result = json.loads(clean_response)
            
            # 兼容新的两层结构
            if 'analysis' in result and isinstance(result['analysis'], dict):
                analysis_data = result['analysis']
                logger.info(f"✅ JSON解析成功 (analysis结构), 包含键: {list(analysis_data.keys())}")
            else:
                # 兼容旧的单层结构
                analysis_data = result
                logger.info(f"✅ JSON解析成功 (单层结构), 包含键: {list(analysis_data.keys())}")
            
            # 关键检查：related_articles的格式
            if 'related_articles' in analysis_data:
                articles = analysis_data['related_articles']
                if isinstance(articles, list) and len(articles) > 0:
                    first_item = articles[0]
                    if isinstance(first_item, dict):
                        has_content = 'content' in first_item and first_item['content']
                        logger.info(f"🎉 [格式正确] related_articles 是对象数组，第一项有content: {has_content}")
                        if has_content:
                            logger.info(f"✨ [内容预览] {first_item.get('number', '?')} - {first_item['content'][:50]}...")
                    elif isinstance(first_item, str):
                        logger.warning(f"⚠️ [格式错误] related_articles 是字符串数组！第一项: {first_item}")
                        logger.warning("❌ AI未遵守提示词要求，将启动数据库补充机制")
                else:
                    logger.warning(f"⚠️ related_articles 为空或格式异常: {type(articles)}")

            # 验证并填充必需的键，适配多种返回格式
            final_result = {}
            
            # 规范化 key_points
            if 'key_points' in analysis_data and analysis_data['key_points']:
                final_result['key_points'] = analysis_data['key_points']
            else:
                final_result['key_points'] = analysis_data.get('legal_relations', [])

            # 规范化 related_articles（重点处理）
            raw_articles = analysis_data.get('related_articles') or analysis_data.get('applicable_articles', [])
            final_result['related_articles'] = self._normalize_articles(raw_articles)

            # 规范化 preliminary_advice
            if 'preliminary_advice' in analysis_data and analysis_data['preliminary_advice']:
                final_result['preliminary_advice'] = analysis_data['preliminary_advice']
            else:
                final_result['preliminary_advice'] = analysis_data.get('rights_obligations', '')

            # 保留其他有价值的字段
            final_result['risks'] = analysis_data.get('risks', [])
            final_result['solutions'] = analysis_data.get('solutions', [])

            # 检查数据质量
            if not final_result['key_points']:
                logger.warning("key_points为空")
                final_result['key_points'] = ["未能识别到具体的法律要点,请提供更详细的场景描述"]
            if not final_result['preliminary_advice']:
                logger.warning("preliminary_advice为空")
                final_result['preliminary_advice'] = "建议咨询专业律师以获取针对性的法律意见。"
            
            logger.info(f"场景分析成功: {len(final_result['key_points'])}个要点, {len(final_result['related_articles'])}条相关条文")
            
            # 详细记录条文数据，便于调试
            if final_result['related_articles']:
                for idx, article in enumerate(final_result['related_articles']):
                    has_content = 'content' in article and article['content']
                    content_preview = article.get('content', '')[:50] if has_content else '无内容'
                    logger.info(f"  条文{idx+1}: {article.get('number', '无编号')} - content存在: {has_content} - 预览: {content_preview}")
            else:
                logger.warning("  未返回任何相关条文")
            
            return {"analysis": final_result}
            
        except json.JSONDecodeError as e:
            logger.error(f"JSON解析失败: {e}")
            logger.error(f"原始响应: {response_str}")
            logger.error(f"清理后的响应: {clean_response if 'clean_response' in locals() else 'N/A'}")
            
            # 返回包含原始回答的友好错误格式
            return {
                "analysis": {
                    "key_points": ["AI返回了非结构化的回答"],
                    "related_articles": [],
                    "preliminary_advice": f"AI分析结果:\n\n{response_str[:500]}\n\n(注: AI未能按标准格式返回,以上为原始回复。建议重新描述场景或咨询专业律师。)"
                }
            }
        except Exception as e:
            logger.error(f"场景分析处理异常: {e}", exc_info=True)
            return {
                "analysis": {
                    "key_points": ["处理AI响应时出现错误"],
                    "related_articles": [],
                    "preliminary_advice": f"系统错误: {str(e)}。请稍后重试。"
                }
            }

    @lru_cache(maxsize=100)
    def explain_article_legacy(self, article_number: str, article_content: str) -> Optional[str]:
        """解释法条内容
        
        Args:
            article_number: 条文编号，如"第一条"
            article_content: 条文内容
            
        Returns:
            AI生成的条文解释，如果失败返回None
        """
        try:
            system_prompt = """你是一位专业的法律专家，专门解读中华人民共和国民法典。
请用通俗易懂的语言解释法条，包括：
1. 条文的核心含义
2. 适用场景和实际应用
3. 与其他相关法条的关系
4. 实际案例说明（如果适用）

请保持专业性的同时，让普通人也能理解。"""

            user_prompt = f"""请解释民法典{article_number}：

条文内容：
{article_content}

请提供详细的解释说明。"""

            messages = [
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": user_prompt}
            ]
            
            response = self._make_request(messages, temperature=0.7, max_tokens=1000)
            
            if response:
                explanation = self._extract_content(response)
                if explanation:
                    logger.info(f"成功生成条文解释: {article_number}")
                    return explanation
            
            logger.warning(f"生成条文解释失败: {article_number}")
            return None
            
        except Exception as e:
            logger.error(f"解释条文时发生错误: {e}")
            return None
    
    
    
    def get_service_status(self) -> Dict:
        """获取AI服务状态"""
        try:
            # 简单的健康检查
            test_messages = [
                {"role": "system", "content": "你是AI助手"},
                {"role": "user", "content": "你好"}
            ]
            
            start_time = time.time()
            response = self._make_request(test_messages, max_tokens=10)
            response_time = time.time() - start_time
            
            if response:
                return {
                    "status": "healthy",
                    "model": self.model_name,
                    "response_time": round(response_time, 3),
                    "api_available": True
                }
            else:
                return {
                    "status": "unhealthy",
                    "model": self.model_name,
                    "api_available": False,
                    "error": "API请求失败"
                }
                
        except Exception as e:
            return {
                "status": "error",
                "model": self.model_name,
                "api_available": False,
                "error": str(e)
            }

# 创建全局AI服务实例
ai_service = AIService()
